﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using QQ2564874169.Nubbo;
using Tests.Nubbo.Mocks;

namespace Tests.Nubbo
{
    [TestClass]
    public class 整体测试
    {
        [TestMethod]
        public void 调用远程服务并得到返回值()
        {
            var server = new MockServer();
            var config = new NubboConfig
            {
                GetResolver = () =>
                {
                    var resolver = new MockResolver();
                    resolver.OnResolve += type =>
                    {
                        if (type == typeof(IService))
                            return new HaveReturnValueService();
                        if (type == typeof(IServiceInvoker))
                            return new MockInvoker(server);
                        if (type == typeof(IObjectInput))
                            return new JsonInput();
                        if (type == typeof(IObjectOutput))
                            return new JsonOutput();
                        return Activator.CreateInstance(type);
                    };
                    return resolver;
                }
            };
            var serviceManager = new ServiceManager(config);
            serviceManager.LoadService(typeof(HaveReturnValueService));
            serviceManager.Start(server);

            var req = new MockRequest("have_return_value")
            {
                Id = Guid.NewGuid(),
                Name = Guid.NewGuid().ToString(),
                CreateTime = DateTime.Now
            };

            using (var res = serviceManager.GetResponse(req))
            {
                var data = res.GetResult<HaveReturnValueService.Result>();

                Assert.AreEqual(req.Id, data.Id);
                Assert.AreEqual(req.Name, data.Name);
                Assert.AreEqual(req.CreateTime.Value.ToString(), data.CreateTime.Value.ToString());
            }
        }

        [TestMethod]
        public void 远程服务没有返回值时获取返回值会报错只能使用Wait()
        {
            var server = new MockServer();
            var config = new NubboConfig
            {
                GetResolver = () =>
                {
                    var resolver = new MockResolver();
                    resolver.OnResolve += type =>
                    {
                        if (type == typeof(IService))
                            return new NoReturnValueService();
                        if (type == typeof(IServiceInvoker))
                            return new MockInvoker(server);
                        if (type == typeof(IObjectInput))
                            return new JsonInput();
                        if (type == typeof(IObjectOutput))
                            return new JsonOutput();
                        return Activator.CreateInstance(type);
                    };
                    return resolver;
                }
            };
            var serviceManager = new ServiceManager(config);
            serviceManager.LoadService(typeof(NoReturnValueService));
            serviceManager.Start(server);

            var req = new MockRequest("no_return_value")
            {
                Id = Guid.NewGuid(),
                Name = Guid.NewGuid().ToString(),
                CreateTime = DateTime.Now
            };

            using (var res = serviceManager.GetResponse(req))
            {
                var count = 0;
                try
                {
                    res.GetResult<HaveReturnValueService.Result>();
                }
                catch (ResponseException)
                {
                    count++;
                }
                res.Wait();

                Assert.AreEqual(1, count);
            }
        }

        [TestMethod]
        public void Response只要已经执行完毕Completed事件就必定会触发()
        {
            var server = new MockServer();
            var config = new NubboConfig
            {
                GetResolver = () =>
                {
                    var resolver = new MockResolver();
                    resolver.OnResolve += type =>
                    {
                        if (type == typeof(IService))
                            return new NoReturnValueService();
                        if (type == typeof(IServiceInvoker))
                            return new MockInvoker(server);
                        if (type == typeof(IObjectInput))
                            return new JsonInput();
                        if (type == typeof(IObjectOutput))
                            return new JsonOutput();
                        return Activator.CreateInstance(type);
                    };
                    return resolver;
                }
            };
            var serviceManager = new ServiceManager(config);
            serviceManager.LoadService(typeof(NoReturnValueService));
            serviceManager.Start(server);

            var req = new MockRequest("no_return_value")
            {
                Id = Guid.NewGuid(),
                Name = Guid.NewGuid().ToString(),
                CreateTime = DateTime.Now
            };

            using (var res = serviceManager.GetResponse(req))
            {
                var count = 0;
                res.Wait();

                Assert.AreEqual(0, count);
                res.Completed += (s, e) =>
                {
                    count++;
                };
                Assert.AreEqual(1, count);
            }
        }
    }

    [ServiceName("have_return_value")]
    public class HaveReturnValueService : IService
    {
        public void Do(ServiceContext context)
        {
            context.Result.Data = context.Request.Param.Param;
        }

        public class Result
        {
            public Guid Id { get; set; }
            public string Name { get; set; }
            public DateTime? CreateTime { get; set; }
        }
    }

    [ServiceName("no_return_value")]
    public class NoReturnValueService : IService
    {
        public void Do(ServiceContext context)
        {

        }
    }
}
